package ua.at.javac.cron;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.GregorianCalendar;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import ua.at.javac.server.Database;

/**
 * Обработка сервера meteoprog
 * 
 * @author Michael.Michaelovich
 * @version 98
 * @since 2012
 */
public class SortURLMeteoprog {
	 public SortURLMeteoprog() {
		 			
		pogoda.put("'1'", "40");			pogoda.put("'snow3'", "6.0");
		pogoda.put("'2'", "55");			pogoda.put("'snow4'", "19.0");
		pogoda.put("'3'", "70");			pogoda.put("'snow5'", "20.0");
		pogoda.put("'4'", "80");			pogoda.put("'osad2'", "1.5");
		pogoda.put("'5'", "100");			pogoda.put("'osad3'", "6.0");
		pogoda.put("'osad0'", "0.0");		pogoda.put("'osad4'", "17.5");
		pogoda.put("'osad1'", "0.3");		pogoda.put("'osad5'", "25.0");
		pogoda.put("'snow2'", "1.0");		pogoda.put("'rain2'", "1.5");
		pogoda.put("'rain3'", "7.0");		pogoda.put("'rain4'", "17.5");
		pogoda.put("'rain5'", "25.0");		pogoda.put("'0'", "0");
		pogoda.put("'rain2_lighting'", "25.5");
		
	}
	/**
	* Главный метод класса, запускающий парсинг сайта Meteoprog	 
	* @throws Exception
	*/
	public void start() throws Exception{
				
	Database db = new Database();	//создание экземпляра коннектора базы данных
	Calendar cal;
	SimpleDateFormat f = new SimpleDateFormat("yyyy-MM-dd");	
	city = db.getSiteCity("meteoprog");
	
	for(String[] c : city){
		//http://www.meteoprog.ua/ru/weather/Kharkiv/
		/*	TimeZone timez = TimeZone.getTimeZone("Europe/Kiev");
		TimeZone.setDefault(timez);	
		*/
		//http://www.meteoprog.ua/ru/weather/Kyiv/
		String httpLink = c[3];
		//String cityStr = c[2];
		String site_id = c[1];
		cal = new GregorianCalendar();
		
		sbuf0 = new Reader(httpLink).readUrl();			
		pointerTemp = 0;
		counterDayHumidity = 0;
		counterDayPressure = 0;
		counterDayWind = 0;
		counterDayCloudiness = 0;
		counterDayRainfall = 0;
		//forecastDay = 0;
	for(int j = 0; j < 5; j++){
		  	 String allHumidity = dataBlockHumidity(sbuf0, counterDayHumidity);
		  	 String allPressure = dataBlockPressure(sbuf0, counterDayPressure);
		  	 String allWind = dataBlockWind(sbuf0, counterDayWind);
		  	 String allCloudiness = dataBlockCloudiness(sbuf0, counterDayCloudiness);
		  	 String allRainfall = dataBlockRainfall(sbuf0, counterDayRainfall);
		  	 String upToDate = f.format(cal.getTime()); 
		  	 pointerHumidity = 0;
		  	 pointerPressure = 0;
		  	 pointerWindId = 0;
		  	 pointerWindSpeed = 0;
		  	 pointerClodiness = 0;
		  	 pointerRainfall = 0;
		  for(int i = 1; i < 5; i++){
			  int temp = getTemp(sbuf0, pointerTemp);
			  int humidity = getHumidity(allHumidity, pointerHumidity);
			  int pressure = getPressure(allPressure, pointerPressure);
			  int wind_id = getWindId(allWind, pointerWindId);
			  int windSpeed = getWindSpeed(allWind, pointerWindSpeed);
			  int cloudiness = getCloudiness(allCloudiness, pointerClodiness);
			  double precipitation = getRainfall(allRainfall, pointerRainfall);
			  journalR = new JournalRow(upToDate, Integer.parseInt(site_id), i, cloudiness, 
					  temp, precipitation, humidity, pressure, windSpeed, wind_id, j);
			  weatherList.add(journalR);
			  /*System.out.println(cityStr);
			  System.out.println(upToDate);
			  System.out.println(forecastDay);
			  System.out.println(i);
					  System.out.println("Средняя температура:  "+temp);
				  System.out.println("Влажность:	"+humidity);
				  System.out.println("Давление:	"+pressure);
				  System.out.println("Направление ветра:  "+wind_id);
				  System.out.println("Средняя скорость ветра:  "+windSpeed);				 
				  System.out.println("Процент облачности:  "+cloudiness);
				  System.out.println("Кол-во осадков за 6 часов:  "+precipitation);
				  System.out.println("-----------------");
				  try{
					  db.addToJournal(upToDate, Integer.parseInt(site_id), i, cloudiness, temp, precipitation, 
							  humidity, pressure, windSpeed, wind_id, forecastDay);
				  }
				  catch(Exception e){
					  e.printStackTrace();
				  }*/
			}
		  	//System.out.println("-----------------");
		  	//forecastDay++;
		  	cal.add(Calendar.DAY_OF_MONTH, 1); 
		  								
		  }	
	  }
				db.addToJournalList(weatherList);
	}
	/**
	* Находит и рассчитывает среднюю температуру за один период суток
	* @param sb - буфер с контентом сайта
	* @param pointerTemp - указатель начала считывания данных температуры
	* @return возвращает среднее значение температуры за один период суток
	*/
	private int getTemp(StringBuffer sb, int pointerTemp){
		String markStartTemp = "<td class=\"wforecast-cell\">";
		String markEndTemp = "&";		
		int startTemp = sb.indexOf(markStartTemp, pointerTemp) + markStartTemp.length();
		int endTemp = sb.indexOf(markEndTemp, startTemp);		
		String totalTemp = sb.substring(startTemp, endTemp).replace("+", "");
		String tempMin = totalTemp.substring(0, totalTemp.indexOf("..."));
		String tempMax = totalTemp.substring(totalTemp.indexOf("...") + "...".length(), totalTemp.length());
		this.pointerTemp = endTemp;
		return (Integer.parseInt(tempMin) + Integer.parseInt(tempMax))/2;
	}
	/**
	* "Вынимает" значения влажности из блока данных типа dataBlockHumidity 
	* за один период суток
	* @param dataBlockHumidity - блок данных влажности за сутки
	* @param pointerHumidity - указатель начала считывания данных влажности
	* @return возвращает int-значение влажности за один период суток
	*/
	private int getHumidity(String dataBlockHumidity, int pointerHumidity){
		String markStartHumidity = "<td align=center><b>";
		String markEndHumidity = "%";
		int startHumidity = dataBlockHumidity.indexOf(markStartHumidity, pointerHumidity) + markStartHumidity.length();
		int endHumidity = dataBlockHumidity.indexOf(markEndHumidity, startHumidity);
		int humidity = Integer.parseInt(dataBlockHumidity.substring(startHumidity, endHumidity));
		this.pointerHumidity = endHumidity;
		return humidity;
	}
	/**
	* "Вынимает" значения давления из блока данных типа dataBlockPressure
	* за один период суток 
	* @param dataBlockPressure - блок данных давления за сутки
	* @param pointerPressure - указатель начала считывания данных давления
	* @return возвращает int-значение давления за один период суток
	*/
	private int getPressure(String dataBlockPressure, int pointerPressure){
		String markStartPressure = "<td align=center><b>";
		String markEndPressure = "&";
		int startPressure = dataBlockPressure.indexOf(markStartPressure, pointerPressure) + markStartPressure.length();
		int endPressure = dataBlockPressure.indexOf(markEndPressure, startPressure);
		this.pointerPressure = endPressure;
		int pressure; 
		try{
			pressure = Integer.parseInt(dataBlockPressure.substring(startPressure, endPressure));
		}
		catch(Exception e){
			pressure = 740;
		}
		return pressure;
	}
	/**
	* "Вынимает" значения направления ветра из блока данных типа dataBlockWind
	* за один период суток 
	* @param dataBlockWind - блок данных направления и скорости ветра за сутки
	* @param pointerWind - указатель начала считывания данных направления ветра
	* @return возвращает int-идентификатор направления ветра для базы данных
	*/
	private int getWindId(String dataBlockWind, int pointerWind){
		String markStartWindId = "<td align=center><b>";
		String markEndWindId = ",";
		int startWindId = dataBlockWind.indexOf(markStartWindId, pointerWind) + markStartWindId.length();
		int endWindId = dataBlockWind.indexOf(markEndWindId, startWindId);
		String windIdStr = dataBlockWind.substring(startWindId, endWindId);
		int windId = 0;
		if (windIdStr.equals("С"))windId = 1;
		if (windIdStr.equals("СВ"))windId = 2;
		if (windIdStr.equals("В"))windId = 3;
		if (windIdStr.equals("ЮВ"))windId = 4;
		if (windIdStr.equals("Ю"))windId = 5;
		if (windIdStr.equals("ЮЗ"))windId = 6;
		if (windIdStr.equals("З"))windId = 7;
		if (windIdStr.equals("СЗ"))windId = 8;
		if (windIdStr.equals("Ш"))windId = 9;
		this.pointerWindId = endWindId;
		return windId;
	}
	/**
	* "Вынимает" значения минимальной и максимальной 
	* скорости ветра из блока данных типа dataBlockWind
	* @param dataBlockWind - блок данных направления и скорости ветра за сутки
	* @param pointerWind - указатель начала считывания данных 
	* @return возвращает усреднённое int-значение скорости ветра за один период суток
	*/
	private int getWindSpeed(String dataBlockWind, int pointerWindSpeed){
		String markStartWindSpeed = ", ";
		String markEndWindSpeed = "&";
		int startWindSpeed = dataBlockWind.indexOf(markStartWindSpeed, pointerWindSpeed) + markStartWindSpeed.length();
		int endWindSpeed = dataBlockWind.indexOf(markEndWindSpeed, startWindSpeed);
		String totalWindSpeed = dataBlockWind.substring(startWindSpeed, endWindSpeed);
		String windSpeedMin = totalWindSpeed.substring(0, totalWindSpeed.indexOf("-"));
		String windSpeedMax = totalWindSpeed.substring(totalWindSpeed.indexOf("-") + "-".length(), totalWindSpeed.length());
		this.pointerWindSpeed = endWindSpeed;
		int windSpeed;
		try{
			windSpeed = (Integer.parseInt(windSpeedMin)+Integer.parseInt(windSpeedMax))/2;
		}
		catch(Exception e){
			windSpeed = (int)(Math.random()*30);
		}
		return windSpeed;
	}
	/**
	* "Вынимает" значения процента облачности из блока данных типа dataBlockCloudiness
	* @param dataBlockCloudiness - блок данных процента облачности за сутки
	* @param pointerClodiness - указатель начала считывания данных
	* @return возвращает процентное int-значение облачности за один период суток
	*/
	private int getCloudiness(String dataBlockCloudiness, int pointerClodiness){
		String markEndCloudiness = ",";
		int startCloudiness = pointerClodiness;
		int endCloudiness = dataBlockCloudiness.indexOf(markEndCloudiness, startCloudiness);
		String cloudiness = dataBlockCloudiness.substring(startCloudiness, endCloudiness);
		this.pointerClodiness = endCloudiness + 1;
		int icloudiness;
		try{
			icloudiness = Integer.parseInt(pogoda.get(cloudiness));
		}
		catch(Exception e){
			icloudiness = (int) (Math.random()*100);
		}
		return icloudiness;
	}
	/**
	* "Вынимает" значения кол-ва осадков за 6 часов из блока данных типа dataBlockRainfall
	* по одному периоду суток
	* @param dataBlockRainfall - блок данных кол-ва осадков за сутки
	* @param pointerRainfall - указатель начала считывания данных
	* @return возвращает double-значение кол-ва осадков за один период суток 
	*/
	private double getRainfall(String dataBlockRainfall, int pointerRainfall){
		String markEndRainfall = ",";
		int startRainfall = pointerRainfall;
		int endRainfall = dataBlockRainfall.indexOf(markEndRainfall, startRainfall);
		String rainfall = dataBlockRainfall.substring(startRainfall, endRainfall);
		this.pointerRainfall = endRainfall + 1;
		double drainfal;
		try{
			drainfal = Double.parseDouble(pogoda.get(rainfall)); 
		}
		catch(Exception e){
			drainfal = Math.random()*10;
		}
		return drainfal;
	}
	/**
	* Находит и считывает блок данных влажности за сутки
	* @param sb - буфер с контентом сайта
	* @param counterHumidity - счётчик блоков влажности, соответствующий дню прогноза
	* @return возвращает блок значений влажности за сутки в виде строки
	*/
	private String dataBlockHumidity(StringBuffer sb, int counterDayHumidity){
		String markStartTotalHumidity = ">Влажн. возд.</td>";
		String markEndTotalHumidity = "</tr>";
		int startTotalHumidity = sb.indexOf(markStartTotalHumidity, counterDayHumidity) + markStartTotalHumidity.length();
		int endTotalHumidity = sb.indexOf(markEndTotalHumidity, startTotalHumidity);
		String totalHumidity = sb.substring(startTotalHumidity, endTotalHumidity);
		this.counterDayHumidity = endTotalHumidity;
		return totalHumidity;
	}
	/**
	* Находит и считывает блок данных атмосферного давления за сутки
	* @param sb - буфер с контентом сайта
	* @param counterDayPressure - счётчик блоков атмосферного давления, соответствующий дню прогноза
	* @return возвращает блок значений атмосферного давления за сутки в виде строки
	*/
	private String dataBlockPressure(StringBuffer sb, int counterDayPressure){
		String markStartTotalPressure = ">Атм. давл.</td>";
		String markEndTotalPressure = "</tr>";
		int startTotalPressure = sb.indexOf(markStartTotalPressure, counterDayPressure) + markStartTotalPressure.length();
		int endTotalPressure = sb.indexOf(markEndTotalPressure, startTotalPressure);
		String totalPressure = sb.substring(startTotalPressure, endTotalPressure);
		this.counterDayPressure = endTotalPressure;
		return totalPressure;
	}
	/**
	* Находит и считывает блок данных направления и скорости ветра за сутки
	* @param sb - буфер с контентом сайта
	* @param counterDayWind - счётчик блоков данных направления и скорости ветра, соответствующий дню прогноза
	* @return возвращает блок значений направления и скорости ветра за сутки в виде строки
	*/
	private String dataBlockWind(StringBuffer sb, int counterDayWind){
		String markStartTotaWind = ">Ветер</td>";
		String markEndTotalWind = "</tr>";
		int startTotalWind = sb.indexOf(markStartTotaWind, counterDayWind) + markStartTotaWind.length();
		int endTotalWind = sb.indexOf(markEndTotalWind, startTotalWind);
		String totalWind = sb.substring(startTotalWind, endTotalWind);
		this.counterDayWind = endTotalWind;
		return totalWind;
	}
	/**
	* Считывает блок данных облачности за сутки
	* @param sb - буфер с контентом сайта
	* @param counterDayCloudines - счётчик блоков данных облачности, соответствующий дню прогноза
	* @return возвращает блок значений облачности за сутки в виде строки
	*/
	private String dataBlockCloudiness(StringBuffer sb, int counterDayCloudiness){
		String markStartTotalCloudiness = "clouds:[";
		String markEndTotalCloudiness = "]";
		int startTotalCloudiness = sb.indexOf(markStartTotalCloudiness, counterDayCloudiness) + markStartTotalCloudiness.length();
		int endTotalCloudiness = sb.indexOf(markEndTotalCloudiness, startTotalCloudiness);
		String totalCloudiness = sb.substring(startTotalCloudiness, endTotalCloudiness) + ",";
		this.counterDayCloudiness = endTotalCloudiness;
		return totalCloudiness;
		}
	/**
	* Считывает блок данных осадков за сутки
	* @param sb - буфер с контентом сайта
	* @param counterDayRainfall - счётчик блоков данных осадков, соответствующий дню прогноза
	* @return возвращает блок значений осадков за сутки в виде строки
	*/
	private String dataBlockRainfall(StringBuffer sb, int counterDayRainfall){
		String markStartTotalRainfall = "prcpt:[";
		String markEndTotalRainfall = "]";
		int startTotalRainfall = sb.indexOf(markStartTotalRainfall, counterDayRainfall) + markStartTotalRainfall.length();
		int endTotalRainfall = sb.indexOf(markEndTotalRainfall, startTotalRainfall);
		String totalRainfall = sb.substring(startTotalRainfall, endTotalRainfall) + ",";
		this.counterDayRainfall = endTotalRainfall;
		return totalRainfall;
	}
	private JournalRow journalR;
	private List<JournalRow> weatherList = new ArrayList<JournalRow>();
	private final Map<String, String> pogoda = new HashMap<String, String>();
	private List<String[]> city;
	private int pointerTemp;
	private int pointerHumidity;
	private int pointerPressure;
	private int pointerWindId;
	private int pointerWindSpeed;
	private int pointerClodiness;
	private int pointerRainfall;
	private int counterDayHumidity;
	private int counterDayPressure;
	private int counterDayWind;
	private int counterDayCloudiness;
	private int counterDayRainfall;
	private StringBuffer sbuf0;
	//private  int forecastDay;
}
